home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / lang / SmallEiffel.lha / SmallEiffel / lib_se / parent_list.e < prev    next >
Text File  |  1998-12-22  |  13KB  |  677 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class PARENT_LIST
  17.    -- 
  18.    -- To store the parent list of a class.
  19.    -- 
  20.  
  21. inherit GLOBALS;
  22.  
  23. creation make
  24.    
  25. feature 
  26.    
  27.    base_class: BASE_CLASS;
  28.      -- Where the parent list is written.
  29.       
  30.    start_position: POSITION;
  31.      -- Of the keyword "inherit".
  32.    
  33.    heading_comment: COMMENT;
  34.      -- Global comment of the inherit clause.
  35.    
  36. feature {NONE}
  37.    
  38.    list: ARRAY[PARENT];
  39.       
  40. feature 
  41.    
  42.    make(bc: like base_class; sp: like start_position; 
  43.     hc: like heading_comment; l: like list) is
  44.       require
  45.      bc /= Void;
  46.      sp /= Void;
  47.      l.lower = 1 and not l.empty;
  48.       do
  49.      base_class := bc;
  50.      heading_comment := hc;
  51.      start_position := sp;
  52.      list := l;
  53.       ensure
  54.      base_class = bc;
  55.      start_position = sp;
  56.      heading_comment = hc;
  57.      list = l;
  58.       end;
  59.    
  60.    count: INTEGER is
  61.       do
  62.      Result := list.upper;
  63.       end;
  64.    
  65.    up_to_any_in(pl: FIXED_ARRAY[BASE_CLASS]) is
  66.       local
  67.      i: INTEGER;
  68.      p: PARENT;
  69.      bc: BASE_CLASS;
  70.       do
  71.      from  
  72.         i := list.upper;
  73.      until
  74.         i = 0 
  75.      loop
  76.         p := list.item(i);
  77.         bc := p.type.base_class;
  78.         if not pl.fast_has(bc) then
  79.            pl.add_last(bc);
  80.         end;
  81.         i := i - 1;
  82.      end;
  83.      from  
  84.         i := list.upper;
  85.      until
  86.         i = 0 
  87.      loop
  88.         p := list.item(i);
  89.         bc := p.type.base_class;
  90.         if bc /= class_any then
  91.            bc.up_to_any_in(pl);
  92.         end;
  93.         i := i - 1;
  94.      end;
  95.       end;
  96.  
  97.    base_class_name: CLASS_NAME is
  98.       do
  99.      Result := base_class.name;
  100.       end;
  101.    
  102.    has_redefine(fn: FEATURE_NAME): BOOLEAN is
  103.       require
  104.      fn /= Void
  105.       local
  106.      i: INTEGER;
  107.       do
  108.      from  
  109.         i := 1;
  110.      until
  111.         Result or else i > list.upper
  112.      loop
  113.         Result := list.item(i).has_redefine(fn); 
  114.         i := i + 1;
  115.      end;
  116.       end;
  117.    
  118.    super: PARENT is
  119.       require
  120.      count = 1
  121.       do
  122.      Result := list.first;
  123.       end;
  124.  
  125. feature {TYPE}
  126.  
  127.    smallest_ancestor(ctx: TYPE): TYPE is
  128.       require
  129.      ctx.is_run_type;
  130.       local
  131.      i: INTEGER;
  132.      p: PARENT;
  133.      sa: TYPE;
  134.       do
  135.      from  
  136.         i := list.upper;
  137.      until
  138.         i = 0
  139.      loop
  140.         p := list.item(i);
  141.         sa := p.smallest_ancestor(ctx).run_type;
  142.         if Result = Void then
  143.            Result := sa;
  144.         else
  145.            Result := sa.smallest_ancestor(Result);
  146.         end;
  147.         if Result.is_any then
  148.            i := 0;
  149.         else
  150.            i := i - 1;
  151.         end;
  152.      end;
  153.       ensure
  154.      Result.is_run_type;
  155.       end;
  156.  
  157. feature {BASE_CLASS}
  158.    
  159.    up_to_original(bottom: BASE_CLASS; top_fn: FEATURE_NAME): FEATURE_NAME is
  160.       local
  161.      p1, p2: PARENT;
  162.      fn1, fn2, new_fn: FEATURE_NAME;
  163.      i: INTEGER;
  164.       do
  165.      from
  166.         i := list.upper;
  167.      until
  168.         i = 0 or else fn1 /= Void
  169.      loop
  170.         p1 := list.item(i);
  171.         fn1 := p1.up_to_original(bottom,top_fn);
  172.         i := i - 1;
  173.      end;
  174.      from
  175.      until
  176.         i = 0 
  177.      loop
  178.         p2 := list.item(i);
  179.         fn2 := p2.up_to_original(bottom,top_fn);
  180.         if fn2 /= Void then
  181.            new_fn := p2.do_rename(top_fn);
  182.            if p2.has_select_for(new_fn) then
  183.           p1 := p2;
  184.           fn1 := fn2;
  185.            end;
  186.         end;
  187.         i := i - 1;
  188.      end;
  189.      if fn1 /= Void then
  190.         if fn1.to_string /= top_fn.to_string then
  191.            Result := repeated_inheritance(p1,fn1,top_fn);
  192.         else
  193.            Result := fn1;
  194.         end;
  195.      end;
  196.       end;
  197.  
  198.    clients_for(fn: FEATURE_NAME): CLIENT_LIST is
  199.       require
  200.      fn /= Void
  201.       local
  202.      i: INTEGER;
  203.      cl: CLIENT_LIST;
  204.       do
  205.      from  
  206.         i := list.upper;
  207.      until
  208.         i = 0
  209.      loop
  210.         cl := list.item(i).clients_for(fn); 
  211.         if Result = Void then
  212.            Result := cl;
  213.         elseif cl /= Void then
  214.            Result := Result.append(cl);
  215.         end;
  216.         if Result = Void then
  217.            i := i - 1;
  218.         elseif Result.gives_permission_to_any then
  219.            i := 0;
  220.         else
  221.            eh.cancel;
  222.            i := i - 1;
  223.         end;
  224.      end;
  225.       end;
  226.  
  227.    going_up(trace: FIXED_ARRAY[PARENT]; top: BASE_CLASS; 
  228.         top_fn: FEATURE_NAME;): FEATURE_NAME is
  229.       require
  230.      top /= Void;
  231.      top_fn /= Void
  232.       local
  233.      i: INTEGER;
  234.      p1, p2: PARENT;
  235.      fn1, fn2: FEATURE_NAME;
  236.       do
  237.      from
  238.         i := list.upper;
  239.      until
  240.         fn1 /= Void or else i = 0
  241.      loop
  242.         p1 := list.item(i);
  243.         fn1 := p1.going_up(trace,top,top_fn);
  244.         i := i - 1;
  245.      end;
  246.      from
  247.      until
  248.         i = 0
  249.      loop
  250.         p2 := list.item(i);
  251.         fn2 := p2.going_up(trace,top,top_fn);
  252.         if fn2 /= Void then
  253.            if p2.has_select_for(fn2) then
  254.           p1 := p2;
  255.           fn1 := fn2;
  256.            end;
  257.         end;
  258.         i := i - 1;
  259.      end;
  260.      Result := fn1;
  261.       end;
  262.  
  263.    is_a_vncg(t1, t2: TYPE): BOOLEAN is
  264.       require
  265.      t1.run_type = t1;
  266.      t2.run_type = t2;
  267.      t2.generic_list /= Void;
  268.      eh.empty
  269.       local
  270.      i: INTEGER;
  271.       do
  272.      from
  273.         i := list.upper;
  274.      until
  275.         Result or else i = 0
  276.      loop
  277.         Result := list.item(i).is_a_vncg(t1,t2);
  278.         i := i - 1;
  279.      end;
  280.       ensure
  281.      eh.empty
  282.       end;
  283.  
  284.    has(fn: FEATURE_NAME): BOOLEAN is
  285.       local
  286.      i: INTEGER;
  287.       do
  288.      from
  289.         i := list.upper;
  290.      until
  291.         Result or else i = 0
  292.      loop
  293.         Result := list.item(i).has(fn);
  294.         i := i - 1;
  295.      end;
  296.       end;
  297.    
  298.    collect_invariant(rc: RUN_CLASS) is
  299.       require
  300.      rc /= Void
  301.       local
  302.      i: INTEGER;
  303.       do
  304.      from
  305.         i := list.upper;
  306.      until
  307.         i = 0
  308.      loop
  309.         list.item(i).type.base_class.collect_invariant(rc);
  310.         i := i - 1;
  311.      end;
  312.       end;
  313.    
  314.    inherit_cycle_check is
  315.       local
  316.      i: INTEGER;
  317.      p: PARENT;
  318.      bc: BASE_CLASS;
  319.       do
  320.      from  
  321.         i := list.upper;
  322.      until
  323.         i = 0
  324.      loop
  325.         p := list.item(i);
  326.         bc := p.type.base_class;
  327.         if bc = Void then
  328.            eh.add_position(p.start_position);
  329.            fatal_error(fz_cnf);
  330.         else
  331.            bc.inherit_cycle_check;
  332.         end;
  333.         i := i - 1;
  334.      end;
  335.       end;
  336.  
  337.    has_parent(c: BASE_CLASS): BOOLEAN is
  338.       require
  339.      not c.is_any
  340.       local
  341.      i: INTEGER;
  342.      bc: BASE_CLASS;
  343.       do
  344.      from  
  345.         i := list.upper;
  346.      until
  347.         i = 0
  348.      loop
  349.         bc := list.item(i).type.base_class;
  350.         if c = bc then
  351.            Result := true;
  352.            i := 0;
  353.         elseif bc.is_subclass_of_aux(c) then
  354.            Result := true;
  355.            i := 0;
  356.         else
  357.            i := i - 1;
  358.         end;
  359.      end;
  360.       end;
  361.  
  362. feature {BASE_CLASS}
  363.    
  364.    first_parent_for(c: BASE_CLASS): PARENT is
  365.      -- Gives the first parent going to `c'.
  366.       local
  367.      i: INTEGER;
  368.      pbc: BASE_CLASS;
  369.       do
  370.      from  
  371.         i := 1;
  372.      until
  373.         Result /= Void
  374.      loop
  375.         Result := list.item(i);
  376.         pbc := Result.type.base_class;
  377.         if pbc = c then
  378.         elseif pbc.is_subclass_of(c) then
  379.         else
  380.            Result := Void;
  381.         end;
  382.         i := i + 1;
  383.      end;
  384.       ensure
  385.      Result /= Void
  386.       end;
  387.    
  388.    next_parent_for(c: BASE_CLASS; previous: PARENT): like previous is
  389.      -- Gives the next one or Void.
  390.       local
  391.      i: INTEGER;
  392.      pbc: BASE_CLASS;
  393.       do
  394.      from  
  395.         from
  396.            i := 1;
  397.         until
  398.            Result = previous
  399.         loop
  400.            Result := list.item(i);
  401.            i := i + 1;
  402.         end;
  403.         Result := Void;
  404.      until
  405.         Result /= Void or else i > list.count
  406.      loop
  407.         Result := list.item(i);
  408.         pbc := Result.type.base_class;
  409.         if pbc = c then
  410.         elseif pbc.is_subclass_of(c) then
  411.         else
  412.            Result := Void;
  413.         end;
  414.         i := i + 1;
  415.      end;
  416.       end;
  417.  
  418. feature {BASE_CLASS}
  419.  
  420.    header_comment_for(ci: CLASS_INVARIANT) is
  421.       local
  422.      i: INTEGER;
  423.       do
  424.      from
  425.         i := list.upper;
  426.      until
  427.         i = 0 or else ci.header_comment /= Void
  428.      loop
  429.         list.item(i).type.base_class.header_comment_for(ci);
  430.         i := i - 1;
  431.      end;
  432.       end;
  433.  
  434. feature {BASE_CLASS}
  435.    
  436.    get_started is
  437.       local
  438.      i1, i2: INTEGER;
  439.      p1, p2: PARENT;
  440.       do
  441.      from  
  442.         i1 := list.upper;
  443.      until
  444.         i1 = 0
  445.      loop
  446.         list.item(i1).get_started(Current);
  447.         i1 := i1 - 1;
  448.      end;
  449.      if list.upper > 1 then
  450.         -- Checking select :
  451.         from  
  452.            i2 := list.upper;
  453.         until
  454.            i2 = 1
  455.         loop
  456.            from
  457.           i1 := 1;
  458.            invariant
  459.           i1 < i2 + 1
  460.            variant
  461.           i2 - i1
  462.            until
  463.           i1 = i2
  464.            loop
  465.           p1 := list.item(i1);
  466.           p2 := list.item(i2);
  467.           p1.multiple_check(p2);
  468.           p2.multiple_check(p1);
  469.           i1 := i1 + 1;
  470.            end;
  471.            i2 := i2 - 1;
  472.         end;
  473.      end;
  474.       end;
  475.  
  476. feature {BASE_CLASS}
  477.  
  478.    look_up_for(rc: RUN_CLASS; fn: FEATURE_NAME): E_FEATURE is
  479.       local
  480.      i: INTEGER;
  481.      p1, p2: PARENT;
  482.      f1, f2: E_FEATURE;
  483.       do
  484.      from
  485.         i := list.upper;
  486.      until
  487.         f1 /= Void or else i = 0
  488.      loop
  489.         p1 := list.item(i);
  490.         f1 := p1.look_up_for(rc,fn);
  491.         i := i - 1;
  492.      end;
  493.      from
  494.      until
  495.         i = 0 
  496.      loop
  497.         p2 := list.item(i);
  498.         f2 := p2.look_up_for(rc,fn);
  499.         if f2 = Void then
  500.         elseif f1 = f2 then
  501.         elseif not f2.is_merge_with(f1,rc) then
  502.            eh.add_position(start_position);
  503.            eh.add_position(f1.start_position);
  504.            eh.add_position(f2.start_position);
  505.            fatal_error(fz_ich);
  506.         elseif f2.is_deferred then
  507.         elseif f1.is_deferred then
  508.            f1 := f2;
  509.            p1 := p2;
  510.         elseif p1.has_redefine(fn) then
  511.            if p2.has_redefine(fn) then
  512.            else
  513.           eh.add_position(fn.start_position);
  514.           eh.add_position(p2.start_position);
  515.           eh.add_position(f2.start_position);
  516.           eh.append(em1); 
  517.           eh.print_as_fatal_error;
  518.            end;
  519.         elseif p2.has_redefine(fn) then
  520.            eh.add_position(fn.start_position);
  521.            eh.add_position(p1.start_position);
  522.            eh.add_position(f1.start_position);
  523.            eh.append(em1); 
  524.            eh.print_as_fatal_error;
  525.         else
  526.            eh.add_position(p2.start_position);
  527.            eh.add_position(p1.start_position);
  528.            eh.add_position(f1.start_position);
  529.            eh.add_position(f2.start_position);
  530.            eh.append(em1); 
  531.            eh.print_as_fatal_error;
  532.         end;
  533.         i := i - 1;
  534.      end;
  535.      Result := f1;
  536.       end;
  537.    
  538.    collect_for(code: INTEGER; fn: FEATURE_NAME) is
  539.       require
  540.      code = code_require or else code = code_ensure;
  541.      fn /= Void;
  542.       local
  543.      i: INTEGER;
  544.       do
  545.      from
  546.         i := list.upper;
  547.      until
  548.         i = 0
  549.      loop
  550.         list.item(i).collect_for(code,fn);
  551.         i := i - 1;
  552.      end;
  553.       end;
  554.    
  555.    pretty_print is
  556.       local
  557.      i: INTEGER;
  558.       do
  559.      fmt.set_indent_level(0);
  560.      if fmt.zen_mode then
  561.         fmt.indent;
  562.      else
  563.         fmt.skip(1);
  564.      end;
  565.      fmt.keyword("inherit");
  566.      fmt.set_indent_level(1);
  567.      fmt.indent;
  568.      if heading_comment /= Void then
  569.         heading_comment.pretty_print;
  570.      end;
  571.      from  
  572.         i := 1;
  573.      until
  574.         i > list.upper
  575.      loop
  576.         list.item(i).pretty_print;
  577.         i := i + 1;
  578.      end;
  579.       end;
  580.  
  581. feature {E_PRECURSOR}
  582.  
  583.    precursor_for(p: E_PRECURSOR; wrf: RUN_FEATURE): E_FEATURE is
  584.      -- Look for the feature for `p' which is written inside `wrf'.
  585.       require
  586.      p /= Void;
  587.      wrf /= Void
  588.       local
  589.      i: INTEGER;
  590.      parent: PARENT;
  591.      f2: like precursor_for;
  592.       do
  593.      from  
  594.         i := list.upper;
  595.      until
  596.         Result /= Void or else i = 0 
  597.      loop
  598.         parent := list.item(i);
  599.         Result := parent.precursor_for(p,wrf);
  600.         i := i - 1;
  601.      end;
  602.      if Result = Void then
  603.         eh.add_position(p.start_position);
  604.         fatal_error("Precursor routine not found.");
  605.      end;
  606.      if run_control.all_check then
  607.         from  
  608.         until
  609.            i = 0 
  610.         loop
  611.            parent := list.item(i);
  612.            f2 := parent.precursor_for(p,wrf);
  613.            if f2 /= Void and then f2 /= Result then
  614.           eh.add_position(p.start_position);
  615.           eh.add_position(Result.start_position);
  616.           eh.add_position(f2.start_position);
  617.           fatal_error("Multiple Precursor found (must use %
  618.                   % { ... } selection.");
  619.            end;
  620.            i := i - 1;
  621.         end;
  622.      end;
  623.       end;
  624.    
  625. feature {NONE}
  626.  
  627.    repeated_inheritance(p1: PARENT; fn1, top_fn: FEATURE_NAME): FEATURE_NAME is
  628.       require
  629.      p1 /= void;
  630.      fn1 /= Void;
  631.      top_fn /= Void
  632.       local
  633.      i: INTEGER;
  634.      p2: PARENT;
  635.      bc1: BASE_CLASS;
  636.       do
  637.      from
  638.         bc1 := p1.type.base_class;
  639.         i := list.upper;
  640.      until
  641.         i = 0
  642.      loop
  643.         p2 := list.item(i);
  644.         if p1 /= p2 then
  645.            if bc1 = p2.type.base_class then
  646.           if p2.do_rename(fn1).to_string = top_fn.to_string then
  647.              Result := top_fn;
  648.           elseif p1.do_rename(fn1).to_string = top_fn.to_string then
  649.              Result := top_fn;
  650.           end;
  651.            end;
  652.         end;
  653.         i := i - 1;
  654.      end;
  655.      if Result = Void then
  656.         Result := fn1;
  657.      end;
  658.       ensure
  659.      top_fn /= Void
  660.       end;
  661.         
  662.  
  663. feature {NONE}
  664.  
  665.    em1: STRING is "Inheritance clash.";
  666.  
  667. invariant
  668.    
  669.    base_class /= Void;
  670.    
  671.    list.lower = 1;
  672.    
  673.    not list.empty;
  674.    
  675. end -- PARENT_LIST
  676.  
  677.